home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / GRAPHICS / XVID.ZIP / XVID.CPP next >
Encoding:
C/C++ Source or Header  |  1996-09-09  |  19.8 KB  |  866 lines

  1. // X mode Graphics library
  2. // by Karl Lager
  3. // Sept, 1996
  4.  
  5. // initialize graphics, set resolution, plot point,
  6. // blit image with zoom, flip, rotate, and clipping
  7.  
  8.  
  9. // If you want to contact me with any questions or comments about this
  10. // code, leave a message in the CompuServe gamedev forum (GO GAMEDEV)
  11. // section 3 (DOS games) addressed to 76752,2243
  12.  
  13.  
  14. #include <dos.h>
  15. #include <math.h>
  16.  
  17. // from Tweak.zip
  18. //----------------------------------------------------------------------
  19. //#include "TwkUser.h" // get Register definition
  20.  
  21. /*
  22.     xxxxADDR defines the base port number used to access VGA component xxxx,
  23.     and is defined for xxxx =
  24.         ATTRCON        -    Attribute Controller
  25.         MISC        -    Miscellaneous Register
  26.         VGAENABLE    -    VGA Enable Register
  27.         SEQ            -    Sequencer
  28.         GRACON        -    Graphics Controller
  29.         CRTC        -    Cathode Ray Tube Controller
  30.         STATUS        -    Status Register
  31. */
  32.  
  33. #define ATTRCON_ADDR    0x3c0
  34. #define MISC_ADDR        0x3c2
  35. #define VGAENABLE_ADDR    0x3c3
  36. #define SEQ_ADDR        0x3c4
  37. #define GRACON_ADDR        0x3ce
  38. #define CRTC_ADDR        0x3d4
  39. #define STATUS_ADDR        0x3da
  40.  
  41.  
  42. /*
  43.     Note that the following C definition of Register is not compatible
  44.     with the C++ definition used in the source code of TWEAK itself!
  45. */
  46.  
  47. typedef struct
  48.     {
  49.     unsigned port;
  50.     unsigned char index;
  51.     unsigned char value;
  52.     } Register;
  53.  
  54. typedef Register *RegisterPtr;
  55.  
  56.  
  57.  
  58. Register mode320x200[] =
  59.     {
  60.     { 0x3c2, 0x0, 0x63},
  61.     { 0x3d4, 0x0, 0x5f},
  62.     { 0x3d4, 0x1, 0x4f},
  63.     { 0x3d4, 0x2, 0x50},
  64.     { 0x3d4, 0x3, 0x82},
  65.     { 0x3d4, 0x4, 0x54},
  66.     { 0x3d4, 0x5, 0x80},
  67.     { 0x3d4, 0x6, 0xbf},
  68.     { 0x3d4, 0x7, 0x1f},
  69.     { 0x3d4, 0x8, 0x0},
  70.     { 0x3d4, 0x9, 0x41},
  71.     { 0x3d4, 0x10, 0x9c},
  72.     { 0x3d4, 0x11, 0x8e},
  73.     { 0x3d4, 0x12, 0x8f},
  74.     { 0x3d4, 0x13, 0x28},
  75.     { 0x3d4, 0x14, 0x0},
  76.     { 0x3d4, 0x15, 0x96},
  77.     { 0x3d4, 0x16, 0xb9},
  78.     { 0x3d4, 0x17, 0xe3},
  79.     { 0x3c4, 0x1, 0x1},
  80.     { 0x3c4, 0x4, 0x6},
  81.     { 0x3ce, 0x5, 0x40},
  82.     { 0x3ce, 0x6, 0x5},
  83.     { 0x3c0, 0x10, 0x41},
  84.     { 0x3c0, 0x13, 0x0}
  85.     };
  86.  
  87. Register mode320x240[] =
  88.     {
  89.     { 0x3c2, 0x0, 0xe3},
  90.     { 0x3d4, 0x0, 0x5f},
  91.     { 0x3d4, 0x1, 0x4f},
  92.     { 0x3d4, 0x2, 0x50},
  93.     { 0x3d4, 0x3, 0x82},
  94.     { 0x3d4, 0x4, 0x54},
  95.     { 0x3d4, 0x5, 0x80},
  96.     { 0x3d4, 0x6, 0xd},
  97.     { 0x3d4, 0x7, 0x3e},
  98.     { 0x3d4, 0x8, 0x0},
  99.     { 0x3d4, 0x9, 0x41},
  100.     { 0x3d4, 0x10, 0xea},
  101.     { 0x3d4, 0x11, 0xac},
  102.     { 0x3d4, 0x12, 0xdf},
  103.     { 0x3d4, 0x13, 0x28},
  104.     { 0x3d4, 0x14, 0x0},
  105.     { 0x3d4, 0x15, 0xe7},
  106.     { 0x3d4, 0x16, 0x6},
  107.     { 0x3d4, 0x17, 0xe3},
  108.     { 0x3c4, 0x1, 0x1},
  109.     { 0x3c4, 0x4, 0x6},
  110.     { 0x3ce, 0x5, 0x40},
  111.     { 0x3ce, 0x6, 0x5},
  112.     { 0x3c0, 0x10, 0x41},
  113.     { 0x3c0, 0x13, 0x0}
  114.     };
  115.  
  116. Register mode320x400[] =
  117.     {
  118.     { 0x3c2, 0x0, 0x63},
  119.     { 0x3d4, 0x0, 0x5f},
  120.     { 0x3d4, 0x1, 0x4f},
  121.     { 0x3d4, 0x2, 0x50},
  122.     { 0x3d4, 0x3, 0x82},
  123.     { 0x3d4, 0x4, 0x54},
  124.     { 0x3d4, 0x5, 0x80},
  125.     { 0x3d4, 0x6, 0xbf},
  126.     { 0x3d4, 0x7, 0x1f},
  127.     { 0x3d4, 0x8, 0x0},
  128.     { 0x3d4, 0x9, 0x40},
  129.     { 0x3d4, 0x10, 0x9c},
  130.     { 0x3d4, 0x11, 0x8e},
  131.     { 0x3d4, 0x12, 0x8f},
  132.     { 0x3d4, 0x13, 0x28},
  133.     { 0x3d4, 0x14, 0x0},
  134.     { 0x3d4, 0x15, 0x96},
  135.     { 0x3d4, 0x16, 0xb9},
  136.     { 0x3d4, 0x17, 0xe3},
  137.     { 0x3c4, 0x1, 0x1},
  138.     { 0x3c4, 0x4, 0x6},
  139.     { 0x3ce, 0x5, 0x40},
  140.     { 0x3ce, 0x6, 0x5},
  141.     { 0x3c0, 0x10, 0x41},
  142.     { 0x3c0, 0x13, 0x0}
  143.     };
  144. Register mode360x270[] =
  145.     {
  146.     { 0x3c2, 0x0, 0xe7},
  147.     { 0x3d4, 0x0, 0x6b},
  148.     { 0x3d4, 0x1, 0x59},
  149.     { 0x3d4, 0x2, 0x5a},
  150.     { 0x3d4, 0x3, 0x8e},
  151.     { 0x3d4, 0x4, 0x5e},
  152.     { 0x3d4, 0x5, 0x8a},
  153.     { 0x3d4, 0x6, 0x30},
  154.     { 0x3d4, 0x7, 0xf0},
  155.     { 0x3d4, 0x8, 0x0},
  156.     { 0x3d4, 0x9, 0x61},
  157.     { 0x3d4, 0x10, 0x20},
  158.     { 0x3d4, 0x11, 0xa9},
  159.     { 0x3d4, 0x12, 0x1b},
  160.     { 0x3d4, 0x13, 0x2d},
  161.     { 0x3d4, 0x14, 0x0},
  162.     { 0x3d4, 0x15, 0x1f},
  163.     { 0x3d4, 0x16, 0x2f},
  164.     { 0x3d4, 0x17, 0xe3},
  165.     { 0x3c4, 0x1, 0x1},
  166.     { 0x3c4, 0x4, 0x6},
  167.     { 0x3ce, 0x5, 0x40},
  168.     { 0x3ce, 0x6, 0x5},
  169.     { 0x3c0, 0x10, 0x41},
  170.     { 0x3c0, 0x13, 0x0}
  171.     };
  172.  
  173. Register mode400x300[] =
  174.     {
  175.     { 0x3c2, 0x0, 0xa7},
  176.     { 0x3d4, 0x0, 0x71},
  177.     { 0x3d4, 0x1, 0x63},
  178.     { 0x3d4, 0x2, 0x64},
  179.     { 0x3d4, 0x3, 0x92},
  180.     { 0x3d4, 0x4, 0x65},
  181.     { 0x3d4, 0x5, 0x82},
  182.     { 0x3d4, 0x6, 0x46},
  183.     { 0x3d4, 0x7, 0x1f},
  184.     { 0x3d4, 0x8, 0x0},
  185.     { 0x3d4, 0x9, 0x40},
  186.     { 0x3d4, 0x10, 0x31},
  187.     { 0x3d4, 0x11, 0x80},
  188.     { 0x3d4, 0x12, 0x2b},
  189.     { 0x3d4, 0x13, 0x32},
  190.     { 0x3d4, 0x14, 0x0},
  191.     { 0x3d4, 0x15, 0x2f},
  192.     { 0x3d4, 0x16, 0x44},
  193.     { 0x3d4, 0x17, 0xe3},
  194.     { 0x3c4, 0x1, 0x1},
  195.     { 0x3c4, 0x2, 0xf},
  196.     { 0x3c4, 0x4, 0x6},
  197.     { 0x3ce, 0x5, 0x40},
  198.     { 0x3ce, 0x6, 0x5},
  199.     { 0x3c0, 0x10, 0x41},
  200.     { 0x3c0, 0x13, 0x0}
  201.     };
  202.  
  203.  
  204. /*
  205.     readyVgaRegs() does the initialization to make the VGA ready to
  206.     accept any combination of configuration register settings.
  207.  
  208.     This involves enabling writes to index 0 to 7 of the CRT controller
  209.     (port 0x3d4), by clearing the most significant bit (bit 7) of index
  210.     0x11.
  211. */
  212.  
  213. void readyVgaRegs(void)
  214.     {
  215.     int v;
  216.     outportb(0x3d4,0x11);
  217.     v = inportb(0x3d5) & 0x7f;
  218.     outportb(0x3d4,0x11);
  219.     outportb(0x3d5,v);
  220.     }
  221.  
  222. /*
  223.     outReg sets a single register according to the contents of the
  224.     passed Register structure.
  225. */
  226.  
  227. void outReg(Register r)
  228.     {
  229.     switch (r.port)
  230.         {
  231.         /* First handle special cases: */
  232.  
  233.         case ATTRCON_ADDR:
  234.             inportb(STATUS_ADDR);          /* reset read/write flip-flop */
  235.             outportb(ATTRCON_ADDR, r.index | 0x20);
  236.                                         /* ensure VGA output is enabled */
  237.             outportb(ATTRCON_ADDR, r.value);
  238.             break;
  239.  
  240.         case MISC_ADDR:
  241.         case VGAENABLE_ADDR:
  242.             outportb(r.port, r.value);    /*    directly to the port */
  243.             break;
  244.  
  245.         case SEQ_ADDR:
  246.         case GRACON_ADDR:
  247.         case CRTC_ADDR:
  248.         default:                        /* This is the default method: */
  249.             outportb(r.port, r.index);    /*    index to port               */
  250.             outportb(r.port+1, r.value);/*    value to port+1            */
  251.             break;
  252.         }
  253.     }
  254.  
  255.  
  256. /*
  257.     outRegArray sets n registers according to the array pointed to by r.
  258.     First, indexes 0-7 of the CRT controller are enabled for writing.
  259. */
  260.  
  261. void outRegArray(Register *r, int n)
  262. {
  263.     readyVgaRegs();
  264.     while (n--)
  265.         outReg(*r++);
  266. }
  267.  
  268. //----------------------------------------------------------------------
  269. // * The above is from Tweak.zip by Robert Schmidt
  270. // * See Tweak.zip in the compuserve Gamedev forum hardware library
  271.  
  272.  
  273. int maxx, maxy;              // screen resolution
  274. int xmin,ymin,xmax,ymax;     // scp window
  275. int pagewidth,pageheight,pagesize;
  276. char *vga=(char*) MK_FP(0xA000, 0);
  277. char *activepage, *visiblepage;
  278. unsigned activestart,visiblestart;
  279.  
  280. #define setmin(a,b) if (b<a) a=b
  281. #define setmax(a,b) if (b>a) a=b
  282.  
  283. void initgraphics()
  284. {     union REGS r;
  285.  
  286.     /* Set VGA BIOS mode 13h: */
  287.  
  288.     r.x.ax = 0x0013;
  289.     int86(0x10, &r, &r);
  290. }
  291. // note: the initgraphics function is necesssary to set the palette properly.
  292. //       It also resets the palette whenever called.
  293.  
  294.  
  295. void set320x200()
  296. {
  297.   outRegArray(mode320x200,25);
  298.  
  299.   maxx = 319;
  300.   maxy = 199;
  301.   xmin = 0;
  302.   ymin = 0;
  303.   xmax = maxx;
  304.   ymax = maxy;
  305.   pagewidth = (maxx+1)/4;
  306.   pageheight = maxy+1;
  307.   pagesize = pagewidth * pageheight;
  308.   visiblepage = vga;
  309.   activepage = vga+pagesize;
  310. }
  311. void set320x240()
  312. {
  313.   outRegArray(mode320x240,25);
  314.  
  315.   maxx = 319;
  316.   maxy = 239;
  317.   xmin = 0;
  318.   ymin = 0;
  319.   xmax = maxx;
  320.   ymax = maxy;
  321.   pagewidth = (maxx+1)/4;
  322.   pageheight = maxy+1;
  323.   pagesize = pagewidth * pageheight;
  324.   visiblepage = vga;
  325.   activepage = vga+pagesize;
  326. }
  327. void set320x400()
  328. {
  329.   outRegArray(mode320x400,25);
  330.  
  331.   maxx = 319;
  332.   maxy = 399;
  333.   xmin = 0;
  334.   ymin = 0;
  335.   xmax = maxx;
  336.   ymax = maxy;
  337.   pagewidth = (maxx+1)/4;
  338.   pageheight = maxy+1;
  339.   pagesize = pagewidth * pageheight;
  340.   visiblepage = vga;
  341.   activepage = vga+pagesize;
  342. }
  343. void set360x270()
  344. { outRegArray(mode360x270,25);
  345.  
  346.   maxx = 359;
  347.   maxy = 269;
  348.   xmin = 0;
  349.   ymin = 0;
  350.   xmax = maxx;
  351.   ymax = maxy;
  352.   pagewidth = (maxx+1)/4;
  353.   pageheight = maxy+1;
  354.   pagesize = pagewidth * pageheight;
  355.   visiblepage = vga;
  356.   activepage = vga+pagesize;
  357. }
  358.  
  359. void set400x300()
  360. { outRegArray(mode400x300,25);
  361.  
  362.   maxx = 399;
  363.   maxy = 299;
  364.   xmin = 0;
  365.   ymin = 0;
  366.   xmax = maxx;
  367.   ymax = maxy;
  368.   pagewidth = (maxx+1)/4;
  369.   pageheight = maxy+1;
  370.   pagesize = pagewidth * pageheight;
  371.   visiblepage = vga;
  372.   activepage = vga+pagesize;
  373. }
  374.  
  375.  
  376. void set80x25(void)   // restore text
  377.     {
  378.     union REGS r;
  379.     r.x.ax = 0x0003;
  380.     int86(0x10, &r, &r);
  381.     }
  382.  
  383.  
  384. void wait4retrace(void)
  385. {
  386. unsigned char i;
  387. do
  388.   {
  389.   i=inportb(0x3da);
  390.   }
  391.   while ((i & 8) !=0);     /* while in retrace */
  392. do
  393.   {
  394.   i=inportb(0x3da);
  395.   }
  396.   while ((i & 8)==0);     /* while not in retrace */
  397. /* retrace begins now */
  398. }
  399.  
  400.  
  401. void flippage()
  402. {//unsigned offset;
  403.  if (visiblepage==vga)
  404.    { visiblepage = vga+pagesize;
  405.      activepage = vga;
  406.      visiblestart = pagesize;
  407.      activestart = 0;
  408.    }
  409.   else
  410.    { visiblepage = vga;
  411.      activepage = vga+pagesize;
  412.      visiblestart = 0;
  413.      activestart = pagesize;
  414.    }
  415. // wait4retrace();
  416.   outportb(0x3d4, 0x0C);        /* set high byte */
  417.   outportb(0x3d5, visiblestart >> 8);
  418.   outportb(0x3d4, 0x0D);        /* set low byte */
  419.   outportb(0x3d5, visiblestart & 0xff);
  420.  
  421. }
  422.  
  423. void clearpage(int color,int pct = 100,int r=1)
  424.  // clear the active page to color
  425.  // clear the top pct percent of the page
  426.  
  427.  // r = retrace: apparently, once the video starts to scan a page
  428.  // of memory, it continues scaning that page down to the last pixel,
  429.  // even if the view page has been changed.  If the memory being
  430.  // written to screen is overwritten, this can result in unwanted flicker.
  431.  
  432. { // outportb(0x3c4, 0x02);            // enable all planes
  433.  // outportb(0x3c5, 0x0f );
  434.  int size;
  435.  if (pct<100) size = (int)((long)pageheight*pct/100) *pagewidth;
  436.  else size = pagesize;
  437.  if (r) wait4retrace();
  438.     outport(0x3c4, 0x0f02);
  439.  
  440.   asm { les di, activepage
  441.         mov ax, color
  442.         mov ah, al
  443.         mov dx,ax
  444.         db 0x66 //eax
  445.         shl ax,16
  446.         mov ax,dx
  447.         db 0x66
  448.         xor cx,cx
  449.     mov cx,size
  450.         shr cx,2
  451.         db 0xf3 //rep
  452.         db 0x66 //stosd
  453.         stosw
  454.        }
  455. }
  456.  
  457.  
  458. void clearvga()  // clear the all vga pages to 0
  459. {
  460.  wait4retrace();
  461.     outport(0x3c4, 0x0f02); // enable all planes
  462.  
  463.   asm { db 0x66
  464.         mov di, 0
  465.         les di,vga
  466.         db 0x66 // eax
  467.         mov ax, 0
  468.         db 0x66
  469.         xor cx,cx
  470.     mov cx,0x3FFF
  471.         db 0xf3 //rep
  472.         db 0x66 //stosd
  473.         stosw
  474.        }
  475. }
  476.  
  477. void enableplane(int plane)
  478. { outportb(0x3c4, 0x02);            // enable write plane plane
  479.   outportb(0x3c5, 0x01 << (plane & 3));
  480. }
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487. unsigned getpixel(int x, int y)
  488. { unsigned char *inptr;
  489.   unsigned color;
  490.  
  491.   if (x<0 || y<0 || x>maxx || y>maxy) return(0);
  492.    // enableReadplane(x)
  493.     outportb(0x3ce, 0x04);       // graph controller addr
  494.     outportb(0x3cf, x & 3);
  495.  
  496.   inptr =(unsigned char *) activepage+y*pagewidth+(x>>2);//x/4;
  497.   color = *inptr;
  498.   return color;
  499.  
  500. }
  501.  
  502.  
  503.  
  504.  
  505.  
  506. void putpixel(int x,int y,int color)
  507. { char *outptr;
  508.  
  509.   if (x<0 || y<0 || x>maxx || y>maxy) return;
  510.  
  511.   enableplane(x);
  512.   outptr = activepage+y*pagewidth+(x>>2);//x/4;
  513.  *outptr = color;
  514. }
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521. //_____________________________________________________________________
  522.  
  523. //  virtual screen functions (x,y = 10,000 x 10,000; pixels = 640x480)
  524. //  xmin,ymin,xmax,ymax are pixel values for window
  525. //  You may want to write your own get & setviewport style function to
  526. //  change these values.
  527.  
  528. void setwindow(int left ,int top,int right, int bottom)
  529. { if (left >= 0 && top >= 0 && right <= maxx && bottom <= maxy
  530.       && left <= right && top <= bottom)
  531.   {xmin = left; ymin = top; xmax = right; ymax = bottom;}
  532.   }
  533.  
  534. void vplot(int x,int y,int color) // virtual coordinates
  535. { long ex,ey;
  536.   char *outptr;
  537.  
  538.   ex = x;
  539.   ex *= maxx+1;
  540.   x = ex/10000;
  541.   ey = y;
  542.   ey *= maxy+1;
  543.   y = ey/10000;
  544.  
  545.   if (x<xmin || y<ymin || x>xmax || y>ymax) return;
  546.  
  547.   enableplane(x);
  548.   outptr =activepage+y*pagewidth+x/4;
  549.   *outptr = color;
  550. }
  551.  
  552.  
  553.  
  554.  
  555.  
  556. void ZFRputimage(void *p,int x, int y, int percent, int flip,int angle)
  557.  
  558. // Take a bitmap, scale it by some percent, flip it about its vertical
  559. // or horizontal axis, rotate it counter clockwise by any number of
  560. // degrees, clip it to a window and write it to a 4-plane xmode page.
  561.  
  562. // color 0 is transparent.
  563.  
  564. // x,y are  virtual 10k by 10k screen coordiates. The image is centered
  565. // around x,y
  566.  
  567. // zoom is relative to a 640x480 pixel screen.
  568. // flip: 1=horizontal, 2=vertical, 3=both (0 = no flip)
  569.  
  570. // image is clipped to global variables (xmin,ymin,xmax,ymax);
  571.  
  572. // note zoom and rotate are converted to floating point immediatly.
  573. // If you want use floating point zoom and rotate, just substitute
  574. // double pct and ang for int percent and angle in the parameter list.
  575.  
  576. {
  577. long isin,icos,isin1,icos1,isin2,icos2;
  578. long ex,ey,xofs,yofs,halfy,halfx,wl,hl;
  579. char *inptr,*outptr;
  580. unsigned int wy,inofs,outofs;
  581. int w,h,x1,x2,y0,y1,y2,temp;
  582. double pct,ang;
  583. double sinx,cosx;
  584. int plane;
  585.  
  586. pct = percent;
  587. pct /= 100;
  588.  
  589. ang = angle;
  590. ang *= M_PI/180;
  591.  
  592. //int maxx = getmaxx(); // maxx and maxy are screen boundries
  593. //int maxy = getmaxy(); // rather than buffer boundries.
  594.  
  595. inptr =(char*) p + 4;
  596. //getgrafsize(p,&w,&h);
  597. w = *(int*)p+1;
  598. h = *((int*)p+1)+1;
  599. wl = 65536L*w;
  600. hl = 65526L*h;
  601.  
  602. //convert x,y from virtual 10000x10000 coordinates to screen coordinates
  603. ex = x;
  604. ex *= maxx+1;
  605. x = ex/10000;
  606.  
  607. ey = y;
  608. ey *= maxy+1;
  609. y = ey/10000;
  610.  
  611.  
  612. // find center pixel  (on the texture map)
  613. halfx = ((w-1)/2)*65536L+32767L;
  614. halfy = ((h-1)/2)*65536L+32767L;
  615.  
  616. // check for inbounds
  617.  if  (pct <= 0)   // plot the center pixel
  618.   { if (x<0 || y<0 || x>xmax || y>ymax) return;
  619.     inofs =(int)(long)( 4+(halfx>>16)+(halfy>>16)*w);
  620.     enableplane(x);
  621.     outptr =activepage+y*pagewidth+x/4;
  622.     *outptr = *((char *)p+inofs);
  623.     return;
  624.  }
  625.  
  626. // scale image relative to a 640x480 screen
  627. double xfactor =pct*(maxx+1)/640;
  628. double yfactor =pct*(maxy+1)/480;
  629.  
  630. sinx = sin(ang);
  631. cosx = cos(ang);
  632. // note: for better optimization, this should probably be done earlier
  633. //       in the code.  That will give the coprocessor time to do the
  634. //       calculations while the CPU is busy doing other stuff.
  635.  
  636. // convert the sine and cosine to fixed point
  637. isin = sinx*65536L;
  638. icos = cosx*65536L;
  639. isin1 = isin /xfactor;
  640. icos1 = icos /xfactor;
  641.  
  642. if (flip % 2) icos1 = -icos1;
  643. if (flip > 1) isin1 = -isin1;
  644.  
  645. isin2 = (isin1<<18) + ((isin1>>14) & 0xffff);    // 4x
  646. icos2 = (icos1<<18) + ((icos1>>14) & 0xffff);
  647. // x factor is shifted an extra 2 bits since xmode plots every fourth pixel
  648.  
  649. isin /= yfactor;
  650. icos /= yfactor;
  651. if (flip % 2)
  652.   isin = -isin;
  653. if (flip>1)
  654.   icos = -icos;
  655.  
  656. // calculate y1 and y2(h2)
  657. if (flip % 2)
  658.   halfx = (w/2)*65536L+32767L;
  659. if (flip > 1)
  660.   halfy = (h/2)*65536L+32767L;
  661. temp = (short int)((long)(65536L*y+(sinx*halfx
  662.            -cosx*halfy)*yfactor)>>16);
  663. y0 = temp;
  664. y1 = temp;
  665. temp = (short int)((long)(65536L*y+(sinx*halfx
  666.                +cosx*(h*65536L-halfy))*yfactor)>>16);
  667. setmin(y0,temp);
  668. setmax(y1,temp);
  669. temp = (short int)((long)(65536L*y+(-sinx*(w*65536L-halfx)
  670.                +cosx*(h*65536L-halfy))*yfactor)>>16);
  671. setmin(y0,temp);
  672. setmax(y1,temp);
  673. temp = (short int)((long)(65536L*y+(-sinx*(w*65536L-halfx)
  674.            -cosx*(halfy))*yfactor)>>16);
  675. setmin(y0,temp);
  676. setmax(y1,temp);
  677.  
  678. y0++;
  679. y1++;
  680. if (flip%2)
  681.   halfx = ((w-1)/2)*65536L+32767L;
  682. if (flip>1)
  683.   halfy = ((h-1)/2)*65536L+32767L;
  684.  
  685. setmax(y0,ymin);
  686. setmin(y1,ymax+1);
  687.  
  688. // Image is plotted about x,y
  689.  
  690. for(plane = 0; plane<4; plane++)
  691. { enableplane(plane);
  692.  
  693.   ex =(long)(halfx+isin*(y-y0));
  694.   ey =(long)(halfy-icos*(y-y0));
  695.   for(y2=y0;y2<y1;y2++)
  696.   // y0 = top screen row
  697.   // y2 = current screen row
  698.   // y1 = bottom screen row
  699.   // ex,ey = 16.16 fixed point u,v values of x,y2  (bitmap x,y)
  700.  
  701.     // the following equations are derived from
  702.     //  0 <= ex+(x2-x)*icos1 < w; 0 <= ey+(x2-x)*isin1 < h;
  703.  
  704.     //   { u = ex+(x2-x)*icos1;
  705.     //     v = ey+(x2-x)*isin1;
  706.     //     if (u>=0 and u<w and v>=0 and v<h) plot(u,v -> x2,y2)
  707.     //   }
  708.     {
  709.      x1=xmin;x2=xmax+1;
  710.      if (icos1>0)//((angle  < 90)||(angle >270))
  711.       { if(ex<0) temp =(int)(long)(-(ex-1)/icos1+1+x);
  712.         else temp = (int)(long)(-ex/icos1+x);
  713.             if (temp>x1) x1=temp;
  714.         if(wl-ex<0)temp = (int)(long)((wl-ex)/icos1+x);
  715.         else temp = (int)(long)((wl-ex-1)/icos1+x+1);
  716.             if (temp<x2) x2=temp;
  717.       }
  718.      else if(icos1<0)//((angle  >90)&&(angle < 270))
  719.       { if(wl-ex<0)temp = (int)(long)((wl-ex-1)/icos1+1+x);
  720.         else temp = (int)(long)((wl-ex)/icos1+x);
  721.             if (temp>x1) x1=temp;
  722.         if(ex<0)temp = (int)(long)(-(ex)/icos1+x);
  723.         else temp = (int)(long)((-ex-1)/icos1+1+x);
  724.             if (temp<x2) x2=temp;
  725.       }
  726.          else
  727.           if (ex<0 || (ex>>16) >= w) goto nexty;
  728.  
  729.      if(isin1>0)//((angle  > 0 )&&(angle <180))
  730.       { if (ey<0) temp = (int)(long)(-(ey-1)/isin1+1+x);
  731.         else     temp = (int)(long)(-(ey)/isin1+x);
  732.             if (temp>x1) x1=temp;
  733.         if (hl-ey<0) temp = (int)(long)((hl-ey)/isin1+x);
  734.         else temp = (int)(long)((hl-ey-1)/isin1+1+x);
  735.             if (temp<x2) x2 = temp;
  736.       }
  737.      else if (isin1<0)//(angle  > 180)
  738.       { if(hl-ey<0)temp = (int)(long)((hl-ey-1)/isin1+1+x);
  739.         else temp = (int)(long)((hl-ey)/isin1+x);
  740.             if (temp>x1) x1=temp;
  741.         if (ey<0) temp = (int)(long)(-(ey)/isin1+x);
  742.         else temp = (int)(long)(-(ey-1)/isin1+1+x);
  743.             if (temp<x2) x2 = temp;
  744.       }
  745.          else
  746.           if (ey<0 || (ey>>16) >= h) goto nexty;
  747.  
  748.          // round up to the nearest (4+plane)
  749.          x1 += (plane+4-(x1&3))&3;
  750.  
  751.      if(x2<0)x2=0;if(x1>=x2) goto nexty;
  752.  
  753.      xofs = ex+icos1*(x1-x);
  754.      yofs = ey+isin1*(x1-x);
  755.      wy = (int)(long)(w * (yofs>>16));
  756.  
  757.          outofs = y2*pagewidth + x1/4;
  758.      outptr = activepage + outofs;
  759.  
  760.      //     x2=0;
  761.      // while (x2<w2)
  762.     asm { push ds
  763.       mov ebx,  xofs
  764.       mov edx,  yofs
  765.           ror ebx,  16
  766.           ror edx,  16
  767.           lds si,  inptr
  768.           add si,  wy
  769.           les di,  outptr
  770.       mov cx,x2
  771.           dec cx
  772.           sub cx,x1
  773.           shr cx,2  // width /= 4 for unchained mode
  774.           inc cx
  775.           jcxz zfrdone
  776.           xor dx,dx
  777.           cmp word ptr isin2, 0  // if sin (angle) >= 0
  778.           jl zfrlooptop2
  779.         }
  780. zfrlooptop:
  781.          asm {
  782.               // color=*(p + inofs);
  783.                mov al, [bx+si]
  784.                cmp al,0
  785.                jz zfrskipwrite
  786.               // *(p2+outofs)=color;
  787.                mov es:[di], al
  788.               }
  789. zfrskipwrite:
  790.          asm {
  791.              // outofs++;
  792.                inc di
  793.              // xofs += icos;
  794.                add ebx, icos2
  795.                adc bx,0
  796.              // yofs += isin;
  797.                add edx, isin2
  798.                adc dx,0
  799.              // if (dy>0)
  800.                jz zfrnext
  801.              }
  802. incy:        // inofs += dy*w;
  803.          asm {   add si,w
  804.                  dec dx
  805.                  jnz incy
  806.              }
  807. zfrnext:
  808.          asm { loop zfrlooptop
  809.                jmp zfrdone
  810.              }
  811. zfrlooptop2:
  812.          asm {
  813.               // color=*(p + inofs);
  814.                mov al, [bx+si]
  815.               // if (color != 0)
  816.                cmp al,0
  817.                jz zfrskipwrite2
  818.               // *(p2+outofs)=color;
  819.                mov es:[di], al
  820.               }
  821. zfrskipwrite2:
  822.          asm {
  823.              // outofs++;
  824.                inc di
  825.              // xofs += icos;
  826.                add ebx, icos2
  827.                adc bx,0
  828.              // yofs += isin;
  829.                add edx, isin2
  830.                adc dx,0
  831.              // if (ax != *y)
  832.                jz zfrnext2
  833.              }
  834. decy:
  835.          asm {
  836.                  sub si,w //    add si,ws
  837.                  inc dx
  838.                  jnz decy
  839.              }
  840. zfrnext2:
  841.          asm { loop zfrlooptop2
  842.              }
  843.  
  844.  
  845. zfrdone:
  846.          asm { pop ds
  847.              }
  848. nexty:
  849.          ex -= isin;
  850.  
  851.          ey += icos;
  852. //         outptr += w2;
  853.      }
  854.   } // next plane
  855. }
  856. // note: although the variables u and v appear in my notes, they do not
  857. // appear in the code. I wrote this code before I came across any
  858. // literature on texture mapping.  The variables that most closely
  859. // correspond to this are ex,ey,xofs,and yofs
  860.  
  861.  
  862.  
  863.  
  864.  
  865.  
  866.